﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Awsc.DataAcquisitionSys.Core.Common.Expressions
{
    public class ExpressionEvaluator
    {
        private List<string> operators = new List<string>
        {
            ">", ">=", "<", "<=", "==", "!=", "&&", "||","(",")"
        };

        private Func<bool> _compiledExpression;
        private readonly Dictionary<string, object> _variables = new Dictionary<string, object>();
        private string _currentExpression;
        private List<string> _tokens;

        private List<string> _fields = new List<string>();
        public List<string> Fields { get { return _fields ??= new List<string>(); } }


        public ExpressionEvaluator(string expressionString)
        {
            _currentExpression = expressionString;
            _tokens = Tokenize(expressionString);
            _fields = GetFieldsFromTokens(_tokens);
        }

        public string CurrentExpression { get { return _currentExpression; } }
        public Func<bool> CompiledExpression
        {
            get
            {
                return CompiledExpression;
            }
        }

        public enum OperatorType
        {
            GreaterThan,
            GreaterThanOrEqual,
            LessThan,
            LessThanOrEqual,
            Equal,
            NotEqual,
            And,
            Or
        }

        public void SetVariable<T>(string name, T value)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException("变量名不能为空");

            _variables[name] = value;
        }

        public void SetVariable(string name, object value)
        {
            if (string.IsNullOrWhiteSpace(name))
                throw new ArgumentException("变量名不能为空");

            _variables[name] = value;
        }

        public bool RemoveVariable(string name)
        {
            return _variables.Remove(name);
        }

        public Func<bool> CompileExpression()
        {
            if (string.IsNullOrWhiteSpace(_currentExpression))
                throw new ArgumentException("表达式不能为空");

            _compiledExpression = CompileInternal(_currentExpression);
            return _compiledExpression;
        }

        public bool Evaluate()
        {
            if (_compiledExpression == null)
                CompileExpression();

            return _compiledExpression?.Invoke() ?? false;
        }


        private Func<bool> CompileInternal(string expression)
        {
            var tokenQueue = new Queue<string>(_tokens);
            var expressionTree = ParseExpression(tokenQueue);
            var lambda = Expression.Lambda<Func<bool>>(expressionTree);
            return lambda.Compile();
        }

        private List<string> GetFieldsFromTokens(List<string> tokens)
        {
            var removedOperatorsTokens = tokens.Where(t => !operators.Contains(t)).Distinct();
            var simbolTokens = removedOperatorsTokens.Where(t => !double.TryParse(t, out _) && !bool.TryParse(t, out _));
            return simbolTokens.ToList();
        }

        private List<string> Tokenize(string expression)
        {
            var tokens = new List<string>();
            var current = "";

            for (int i = 0; i < expression.Length; i++)
            {
                char c = expression[i];

                if (char.IsWhiteSpace(c))
                {
                    if (!string.IsNullOrEmpty(current))
                    {
                        tokens.Add(current);
                        current = "";
                    }
                    continue;
                }

                // 检查多字符运算符
                if (i < expression.Length - 1)
                {
                    string twoCharOp = c.ToString() + expression[i + 1];
                    if (IsTwoCharOperator(twoCharOp))
                    {
                        if (!string.IsNullOrEmpty(current))
                        {
                            tokens.Add(current);
                            current = "";
                        }
                        tokens.Add(twoCharOp);
                        i++; // 跳过下一个字符
                        continue;
                    }
                }

                // 检查单字符运算符或括号
                if (IsOperatorChar(c) || c == '(' || c == ')')
                {
                    if (!string.IsNullOrEmpty(current))
                    {
                        tokens.Add(current);
                        current = "";
                    }
                    tokens.Add(c.ToString());
                }
                else
                {
                    current += c;
                }
            }

            if (!string.IsNullOrEmpty(current))
            {
                tokens.Add(current);
            }

            return tokens;
        }

        private bool IsTwoCharOperator(string op)
        {
            return op == ">=" || op == "<=" || op == "==" || op == "!=" || op == "&&" || op == "||";
        }

        private bool IsOperatorChar(char c)
        {
            return c == '>' || c == '<' || c == '=' || c == '!' || c == '&' || c == '|';
        }

        private Expression ParseExpression(Queue<string> tokens)
        {
            return ParseLogicalOr(tokens);
        }

        private Expression ParseLogicalOr(Queue<string> tokens)
        {
            var left = ParseLogicalAnd(tokens);

            while (tokens.Count > 0 && tokens.Peek() == "||")
            {
                tokens.Dequeue(); // 消费 ||
                var right = ParseLogicalAnd(tokens);
                left = Expression.OrElse(left, right);
            }

            return left;
        }

        private Expression ParseLogicalAnd(Queue<string> tokens)
        {
            var left = ParseComparison(tokens);

            while (tokens.Count > 0 && tokens.Peek() == "&&")
            {
                tokens.Dequeue(); // 消费 &&
                var right = ParseComparison(tokens);
                left = Expression.AndAlso(left, right);
            }

            return left;
        }

        private Expression ParseComparison(Queue<string> tokens)
        {
            if (tokens.Peek() == "(")
            {
                tokens.Dequeue(); // 消费 (
                var expr = ParseExpression(tokens);
                if (tokens.Count == 0 || tokens.Dequeue() != ")")
                    throw new FormatException("缺少右括号");
                return expr;
            }

            var left = ParseOperand(tokens);

            if (tokens.Count == 0)
                return left;

            var opToken = tokens.Dequeue();
            var op = ParseOperator(opToken);

            var right = ParseOperand(tokens);

            return CreateComparisonExpression(left, right, op);
        }

        private Expression ParseOperand(Queue<string> tokens)
        {
            if (tokens.Count == 0)
                throw new FormatException("缺少操作数");

            var token = tokens.Peek();

            if (token == "(")
            {
                tokens.Dequeue(); // 消费 (
                var expr = ParseExpression(tokens);
                if (tokens.Count == 0 || tokens.Dequeue() != ")")
                    throw new FormatException("缺少右括号");
                return expr;
            }

            token = tokens.Dequeue();

            // 处理布尔常量
            if (token.Equals("true", StringComparison.OrdinalIgnoreCase))
                return Expression.Constant(true);

            if (token.Equals("false", StringComparison.OrdinalIgnoreCase))
                return Expression.Constant(false);

            // 处理数字常量
            if (double.TryParse(token, out double doubleValue))
                return Expression.Constant(doubleValue);

            if (int.TryParse(token, out int intValue))
                return Expression.Constant(intValue);

            // 处理变量
            if (!_variables.ContainsKey(token))
                throw new KeyNotFoundException($"未找到变量: {token}");

            var value = _variables[token];
            var constant = Expression.Constant(value);

            // 创建类型转换表达式
            if (value is int || value is double || value is float || value is decimal)
            {
                return Expression.Convert(constant, typeof(double));
            }

            return constant;
        }

        private OperatorType ParseOperator(string opToken)
        {
            return opToken switch
            {
                ">" => OperatorType.GreaterThan,
                ">=" => OperatorType.GreaterThanOrEqual,
                "<" => OperatorType.LessThan,
                "<=" => OperatorType.LessThanOrEqual,
                "==" => OperatorType.Equal,
                "!=" => OperatorType.NotEqual,
                _ => throw new FormatException($"无效的运算符: {opToken}")
            };
        }

        private Expression CreateComparisonExpression(Expression left, Expression right, OperatorType op)
        {
            // 确保操作数类型一致
            if (left.Type != right.Type)
            {
                if (left.Type == typeof(double) || right.Type == typeof(double))
                {
                    left = Expression.Convert(left, typeof(double));
                    right = Expression.Convert(right, typeof(double));
                }
                else if (left.Type == typeof(int) || right.Type == typeof(int))
                {
                    left = Expression.Convert(left, typeof(int));
                    right = Expression.Convert(right, typeof(int));
                }
                else
                {
                    throw new InvalidOperationException($"无法比较类型: {left.Type.Name} 和 {right.Type.Name}");
                }
            }

            return op switch
            {
                OperatorType.GreaterThan => Expression.GreaterThan(left, right),
                OperatorType.GreaterThanOrEqual => Expression.GreaterThanOrEqual(left, right),
                OperatorType.LessThan => Expression.LessThan(left, right),
                OperatorType.LessThanOrEqual => Expression.LessThanOrEqual(left, right),
                OperatorType.Equal => Expression.Equal(left, right),
                OperatorType.NotEqual => Expression.NotEqual(left, right),
                _ => throw new ArgumentOutOfRangeException(nameof(op), op, null)
            };
        }
    }
}
